using System.Text.Json;
using System.Text.Json.Serialization;

namespace System;
/// <summary>
/// JsonExtensions
/// </summary>
public static class JsonExtensions
{
    #region static properties
    /// <summary>
    /// 默认序列化setting
    /// </summary>
    /// <value></value>
    private static JsonSerializerOptions _serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)
    {
        MaxDepth = 128,
        NumberHandling = JsonNumberHandling.AllowReadingFromString,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        PropertyNameCaseInsensitive = true,
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
        UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode
    };
    static JsonExtensions()
    {
        _serializerOptions.Converters.Add(new JsonStringEnumConverter());
    }
    #endregion

    /// <summary>
    /// 生成json字符串
    /// </summary>
    /// <param name="value">对象</param>
    /// <param name="settings">配置</param>
    /// <returns>字符串</returns>
    public static string? JsonStringify(this object value, JsonSerializerOptions? settings = null)
    {
        if (value is null) return default;

        return JsonSerializer.Serialize(value, settings ?? _serializerOptions);
    }
    /// <summary>
    /// 转换json为对象
    /// </summary>
    /// <param name="json">字符串</param>
    /// <param name="obj"></param>
    /// <param name="e"></param>
    /// <param name="settings"></param>
    /// <typeparam name="T">类型</typeparam>
    /// <returns>对象</returns>
    public static bool TryJsonParse<T>(this string? json, out T? obj, out Exception? e, JsonSerializerOptions? settings = null)
    {
        if (string.IsNullOrEmpty(json))
        {
            obj = default;
            e = default;
            return false;
        }

        try
        {
            obj = JsonSerializer.Deserialize<T>(json!, settings ?? _serializerOptions);
            e = default;

            return true;
        }
        catch (Exception ex)
        {
            obj = default;
            e = ex;

            return false;
        }
    }
}